package fictional.GUI;

import fictional.Common.ShortCharacterItem;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;

/**
 * Creates a popup which shows a list of other characters, triggered
 * by either searching, editing friends, viewing another character's
 * friends, viewing family, or approving friend requests. 
 */
@SuppressWarnings("serial")
public class AddEditFriendsPopup extends javax.swing.JFrame
{
    List<ShortCharacterItem> friends;
    ArrayList<ShortCharacterItem> siblings;
    ArrayList<ShortCharacterItem> children;
    ArrayList<ShortCharacterItem> marriages;
    List<DrawData> drawDataList;
    GUI gui;
    SortedSet<Integer> friendRequestsSentIDs;
    SortedSet<Integer> alreadyFriendsWithIDs;
    JPanel mainPanel;

    // constructor for showing regular list of character
    public AddEditFriendsPopup(List<ShortCharacterItem> friends, int addEditFriends, final GUI gui, SortedSet<Integer> friendCannotBeAsked, ArrayList<ShortCharacterItem> alreadyFriendsWith)
    {
        this.friends = friends;
        this.gui = gui;
        gui.setEnabled(false);
        gui.setIsEnabled(false);
        this.friendRequestsSentIDs = friendCannotBeAsked;
		this.setIconImage(new ImageIcon(getClass().getResource("resources/windowIcon.gif")).getImage());
        
        initGeneralFrame();

        initFrame(addEditFriends, alreadyFriendsWith);
    }
    
    public void initGeneralFrame()
    {
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        this.setSize(500, 450);
        this.setResizable(false);
        this.setBackground(Color.white);
        this.setAlwaysOnTop(true);
        
        this.addWindowListener(new WindowAdapter() {
        	public void windowClosing(java.awt.event.WindowEvent e) {
                gui.setIsEnabled(true);
                gui.setEnabled(true);
        	}
        });
    }
    
    // constructor for showing a list of family characters, each with its relation
    // to the displayed character.
    public AddEditFriendsPopup(ArrayList<ShortCharacterItem> siblings, ArrayList<ShortCharacterItem> children, ArrayList<ShortCharacterItem> marriages, GUI gui)
    {
        this.siblings = siblings;
        this.children = children;
        this.marriages = marriages;
        this.gui = gui;
        gui.setEnabled(false);
        gui.setIsEnabled(false);
        
        initGeneralFrame();

        initFamilyFrame();
    }
    
    private void initFamilyFrame()
    {
    	JScrollPane jScrollPane1 = new JScrollPane();
    	 mainPanel = new JPanel();
    	jScrollPane1.setViewportView(mainPanel);

    	this.add(jScrollPane1);
    	
    	this.setTitle("View Family Members");

        GridBagLayout gridLayout = new GridBagLayout();
        mainPanel.setLayout(gridLayout);
        
        GridBagConstraints cons = new GridBagConstraints();

        int friendCount = 0;

        drawDataList = new LinkedList<DrawData>();
        
    	if (siblings != null)
    	{
    		for (ShortCharacterItem sibling : siblings)
    		{
    			drawFriendView(sibling, cons, friendCount, "sibling");
    			
                JSeparator seperator = new JSeparator();
                cons.gridx = 0;
                cons.gridy = friendCount + 1;
            	cons.gridwidth = 3;
                cons.insets = new Insets(10, 10, 0, 10);
                mainPanel.add(seperator, cons);

                friendCount += 2;
    		}
    	}
    	
    	if (children != null)
    	{
    		for (ShortCharacterItem child : children)
    		{
    			drawFriendView(child, cons, friendCount, "child");
    			
                JSeparator seperator = new JSeparator();
                cons.gridx = 0;
            	cons.gridwidth = 3;
                cons.gridy = friendCount + 1;
                cons.insets = new Insets(10, 10, 0, 10);
                mainPanel.add(seperator, cons);

                friendCount += 2;
    		}
    	}
    	
    	if (marriages != null)
    	{
    		for (ShortCharacterItem marriedTo : marriages)
    		{
    			drawFriendView(marriedTo, cons, friendCount, "married to");
    			
                JSeparator seperator = new JSeparator();
                cons.gridx = 0;
            	cons.gridwidth = 3;
                cons.gridy = friendCount + 1;
                cons.insets = new Insets(10, 10, 0, 10);
                mainPanel.add(seperator, cons);

                friendCount += 2;
    		}
    	}
    	
        (new ImageLoader(drawDataList)).execute();
    }

    private void initFrame(int addEditFriends, ArrayList<ShortCharacterItem> alreadyFriendsWith)
    {
    	JScrollPane jScrollPane1 = new JScrollPane();
    	mainPanel = new JPanel();
    	jScrollPane1.setViewportView(mainPanel);

    	this.add(jScrollPane1);

        GridBagLayout gridLayout = new GridBagLayout();
        mainPanel.setLayout(gridLayout);
        if (addEditFriends == GUI.ADD_FRIENDS)
        {
            this.setTitle("Approve Friend Requests");
        }
        else if (addEditFriends == GUI.SEARCH_FRIENDS)
        {
        	this.setTitle("Search Friends Results");
        	
        	this.setTitle("Search Friends Results");
        	
        	alreadyFriendsWithIDs = new TreeSet<Integer>();
        	for (ShortCharacterItem item : alreadyFriendsWith)
        	{
        		alreadyFriendsWithIDs.add(item.getId());
        	}
        }
        else if (addEditFriends == GUI.EDIT_FRIENDS)
        {
            this.setTitle("Edit Friends");
        }
        else
        {
        	this.setTitle("View Friends");
        }
        
        this.setResizable(false);

        GridBagConstraints cons = new GridBagConstraints();

        int friendCount = 0;

        drawDataList = new LinkedList<DrawData>();

        for (final ShortCharacterItem friend : friends)
        {
        	final JButton button = new JButton();
        	final JButton ignoreButton = new JButton(); 
        	
        	drawFriendView(friend, cons, friendCount, null);
            
            if (addEditFriends != GUI.VIEW_FRIENDS)
            {
                cons.fill = GridBagConstraints.HORIZONTAL;
                cons.gridx = 3;
                cons.gridy = friendCount;
                cons.insets = new Insets(10, 0, 0, 10);
                
                if (addEditFriends == GUI.ADD_FRIENDS)
                {
                	button.setText("Add");
                	
                	button.addMouseListener(new java.awt.event.MouseAdapter()
                    {
                        public void mouseClicked(java.awt.event.MouseEvent evt)
                        {
                        	if (button.isEnabled())
                        	{
                                addFriendButtonMouseClicked(button, ignoreButton, friend);
                        	}
                        }
                    });
                }
                else if (addEditFriends == GUI.SEARCH_FRIENDS)
                {
                	if (friendRequestsSentIDs.contains(friend.getId()))
                	{
                		button.setText("Request Sent");
                		button.setEnabled(false);
                	}
                	else if (alreadyFriendsWithIDs.contains(friend.getId()))
                	{
                		button.setText("Already Friends");
                		button.setEnabled(false);
                	}
                	else
                	{
                    	button.setText("Request");
                    	
                    	button.addMouseListener(new java.awt.event.MouseAdapter()
                        {
                            public void mouseClicked(java.awt.event.MouseEvent evt)
                            {
                            	if (button.isEnabled())
                            	{
                                    requestFriendButtonMouseClicked(button, friend);
                            	}
                            }
                        });
                	}
                }
                else
                {
                	button.setText("Remove");
                	
                	button.addMouseListener(new java.awt.event.MouseAdapter()
                    {
                        public void mouseClicked(java.awt.event.MouseEvent evt)
                        {
                        	if (button.isEnabled())
                        	{
                                removeFriendButtonMouseClicked(button, friend);
                        	}
                        }
                    });
                }
                
                mainPanel.add(button, cons);
                
                if (addEditFriends == GUI.ADD_FRIENDS)
                {
                    ignoreButton.setText("Ignore");
                    cons.fill = GridBagConstraints.HORIZONTAL;
                    cons.gridx = 4;
                    cons.gridy = friendCount;
                    cons.insets = new Insets(10, 0, 0, 10);
                    
                    ignoreButton.addMouseListener(new java.awt.event.MouseAdapter()
                    {
                        public void mouseClicked(java.awt.event.MouseEvent evt)
                        {
                        	if (button.isEnabled())
                        	{
                                ignoreFriendButtonMouseClicked(ignoreButton, button, friend);
                        	}
                        }
                    });
                	
                    mainPanel.add(ignoreButton, cons);
                }
                
                if (addEditFriends == GUI.ADD_FRIENDS)
                {
                    cons.gridwidth = 5;
                }
                else
                {
                	cons.gridwidth = 4;
                }
            }
            else
            {
            	cons.gridwidth = 3;
            }
            
            if ((friendCount / 2) == friends.size() - 1)
            {
            	cons.anchor = GridBagConstraints.NORTH;
            	cons.weighty = 1.0;
            }

            JSeparator seperator = new JSeparator();
            cons.gridx = 0;
            cons.gridy = friendCount + 1;
            cons.insets = new Insets(10, 10, 0, 10);
            mainPanel.add(seperator, cons);

            friendCount += 2;
        }
        (new ImageLoader(drawDataList)).execute();
    }
    
    // draws a single friend in the frame
    private void drawFriendView(final ShortCharacterItem friend, GridBagConstraints cons, int friendCount, String suffix)
    {
        JLabel friendImageLabel = getFriendLabel(friend);

        cons.fill = GridBagConstraints.HORIZONTAL;
        cons.gridwidth = 1;
        cons.gridx = 0;
        cons.gridy = friendCount;
        cons.insets = new Insets(10, 10, 0, 10);
        mainPanel.add(friendImageLabel, cons);

        JLabel label = new JLabel(friend.getName());
        if (suffix != null)
        {
        	label.setText(label.getText() + " (" + suffix + ")");
        }
        cons.fill = GridBagConstraints.HORIZONTAL;
        cons.gridx = 1;
        cons.gridy = friendCount;
        cons.weightx = 1.0;
        cons.insets = new Insets(10, 0, 0, 70);
        mainPanel.add(label, cons);

        final JButton viewFriendInfoButton = new JButton("View Profile");
        cons.fill = GridBagConstraints.HORIZONTAL;
        cons.gridx = 2;
        cons.weightx = 0.0;
        cons.gridy = friendCount;
        cons.insets = new Insets(10, 0, 0, 10);
        mainPanel.add(viewFriendInfoButton, cons);

        viewFriendInfoButton.addMouseListener(new java.awt.event.MouseAdapter()
        {
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
                viewFriendProfileButtonMouseClicked(evt, friend);
            }
        });
    }

    private void removeFriendButtonMouseClicked(JButton button, ShortCharacterItem friend)
    {
    	this.setAlwaysOnTop(false);
        int response = JOptionPane.showConfirmDialog(null, "Are you sure you want to remove " + friend.getName() + "?", "Remove Friend", JOptionPane.YES_NO_OPTION);
        
        if (response == JOptionPane.OK_OPTION)
        {
        	gui.removeFriend(button, friend);
        }
    	this.setAlwaysOnTop(true);
    }

    private void addFriendButtonMouseClicked(JButton button, JButton secondButton, ShortCharacterItem friend)
    {
    	this.setAlwaysOnTop(false);
        int response = JOptionPane.showConfirmDialog(null, "Are you sure you want to add " + friend.getName() + "?", "Add New Friend", JOptionPane.YES_NO_OPTION);
        
        if (response == JOptionPane.OK_OPTION)
        {
        	gui.approveFriendRequest(button, secondButton, friend);
        }
    	this.setAlwaysOnTop(true);
    }

    private void viewFriendProfileButtonMouseClicked(java.awt.event.MouseEvent evt, ShortCharacterItem friend)
    {
    	this.setAlwaysOnTop(false);
        int response = JOptionPane.showConfirmDialog(null, "Are you sure you want to view " + friend.getName() + "'s profile?", "View Profile", JOptionPane.YES_NO_OPTION);
        
        if (response == JOptionPane.OK_OPTION)
        {
            this.setVisible(false);
            this.dispose();
            gui.setIsEnabled(true);
            gui.setEnabled(true);
            gui.requestFocus();
        	gui.getCharacterForView(friend);
        }
    }
    
    private void requestFriendButtonMouseClicked(JButton button, ShortCharacterItem friend)
    {
    	this.setAlwaysOnTop(false);
        int response = JOptionPane.showConfirmDialog(null, "Are you sure you want to request friendship from " + friend.getName() + "?", "Friend Request", JOptionPane.YES_NO_OPTION);
        
        if (response == JOptionPane.OK_OPTION)
        {
        	gui.sendFriendRequest(button, friend);
        }
    	this.setAlwaysOnTop(true);
    }
    
    private void ignoreFriendButtonMouseClicked(JButton button, JButton secondButton, ShortCharacterItem friend)
    {
    	this.setAlwaysOnTop(false);
        int response = JOptionPane.showConfirmDialog(null, "Are you sure you want to ignore friendship request from " + friend.getName() + "?", "Ignore Friend Request", JOptionPane.YES_NO_OPTION);
        
        if (response == JOptionPane.OK_OPTION)
        {
        	gui.ignoreFriendRequest(button, secondButton, friend);
        }
    	this.setAlwaysOnTop(true);
    }

    private JLabel getFriendLabel(ShortCharacterItem friend)
    {
        JLabel friendImageLabel = new javax.swing.JLabel();
        friendImageLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        friendImageLabel.setPreferredSize(new java.awt.Dimension(50, 50));
        friendImageLabel.setName("friendLabel" + friend.getId());
        java.net.URL imgURL = null;
        
        if (friend.getProfileImage() == null)
        {
        	imgURL = getClass().getResource("resources/defaultProfileImage.jpg");
        }
        else 
        {
            try
            {
                imgURL = new java.net.URL(friend.getProfileImage().getLink());
            } 
            catch (MalformedURLException e)
            {
            	imgURL = getClass().getResource("resources/defaultProfileImage.jpg");
            }	
        }

        DrawData drawData = new DrawData(friendImageLabel, imgURL, 50, 50);
        drawDataList.add(drawData);

        return friendImageLabel;
    }
}
